package com.qiaofang.applet.service.property.service.impl;

import com.google.common.collect.Lists;
import com.qiaofang.applet.common.base.MongoBaseService;
import com.qiaofang.applet.common.context.QfContext;
import com.qiaofang.applet.common.context.QfContextHolder;
import com.qiaofang.applet.common.exception.BusinessException;
import com.qiaofang.applet.constants.EstateSortConstants;
import com.qiaofang.applet.service.other.domain.CityCompany;
import com.qiaofang.applet.service.other.domain.PropertyWaterMark;
import com.qiaofang.applet.service.other.repository.CityCompanyRepository;
import com.qiaofang.applet.service.other.service.CityCompanyService;
import com.qiaofang.applet.service.property.domain.Estate;
import com.qiaofang.applet.service.property.domain.EstateComment;
import com.qiaofang.applet.service.property.domain.EstatePhoto;
import com.qiaofang.applet.service.property.repository.EstateRepository;
import com.qiaofang.applet.service.property.service.CommonService;
import com.qiaofang.applet.service.property.service.EstateService;
import com.qiaofang.applet.service.property.service.dto.*;
import com.qiaofang.applet.service.property.service.mapstruct.EstateMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EstateServiceImpl extends MongoBaseService<Estate, String> implements EstateService {

    private final EstateRepository repository;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private CityCompanyService cityCompanyService;

    @Autowired
    private EstateMapper estateMapper;

    @Autowired
    private CommonService commonService;

    @Autowired
    private CityCompanyRepository cityCompanyRepository;

    @Autowired
    public EstateServiceImpl(EstateRepository repository) {
        super(repository);
        this.repository = repository;
    }

    @Override
    public Estate findByEstateUniqueUuid(String estateUniqueUuid) {
        return repository.findByEstateUniqueUuid(estateUniqueUuid);
    }

    @Override
    public Page<Estate> findAllEstateByParams(EstateQueryDto queryDto, Pageable pageable) {
        // 1、拼查询公共条件
        Query queryCriteria = createFindQuery(queryDto);
        // 2、拼分页参数
        queryCriteria.with(pageable);
         //3、拼排序参数
        if (queryDto.getExistProperty() != null) {
            queryCriteria.with(Sort.by(Sort.Order.desc("coverPicture")));
        }
        createFindSort(queryCriteria, queryDto.getSort());
        // 4、查询记录条件
        long count = mongoTemplate.count(queryCriteria, Estate.class);
        List<Estate> content = new ArrayList<>();
        if (count > 0) {
            // 6、分页查询数据
            content = mongoTemplate.find(queryCriteria, Estate.class);
        }
        return PageableExecutionUtils.getPage(content, pageable, () -> count);
    }

    @Override
    public Page<Estate> getSurroundingEstates(EstateQueryDto queryDto,String estateUniqueUuid,  Pageable pageable) {
        // 1、拼查询公共条件
        Query queryCriteria = createFindQuery(queryDto);
        queryCriteria.addCriteria(Criteria.where("estateUniqueUuid").ne(estateUniqueUuid));
        // 2、拼分页参数
        queryCriteria.with(pageable);
        //3、拼排序参数
        if (queryDto.getExistProperty() != null) {
            queryCriteria.with(Sort.by(Sort.Order.desc("coverPicture")));
        }
        createFindSort(queryCriteria, queryDto.getSort());
        // 4、查询记录条件
        long count = mongoTemplate.count(queryCriteria, Estate.class);
        List<Estate> content = new ArrayList<>();
        if (count > 0) {
            // 6、分页查询数据
            content = mongoTemplate.find(queryCriteria, Estate.class);
        }
        return PageableExecutionUtils.getPage(content, pageable, () -> count);
    }

    @Override
    public List<Estate> findAllEstateByParams(EstateQueryDto queryDto) {
        // 1、拼查询公共条件
        Query queryCriteria = createFindQuery(queryDto);

        createFindSort(queryCriteria, queryDto.getSort());

        List<Estate> estateList = mongoTemplate.find(queryCriteria, Estate.class);
        //PropertyWaterMark propertyWaterMark = getPropertyWaterMark();
        //for (Estate estate : estateList) {
        //    estate.setPhotoUrl(commonService.propertyWaterMark(estate.getPhotoUrl(), propertyWaterMark));
        //}
        return estateList;
    }

    private Query createFindQuery(EstateQueryDto queryDto) {
        Query query = new Query();

        QfContext qfContext = QfContextHolder.getContext();

        Criteria criteria = Criteria.where("corporationCode").is(StringUtils.defaultString(queryDto.getCorporationCode(), qfContext.getCorporationCode()));

        if (StringUtils.isNotBlank(queryDto.getCityCode())) {
            criteria.and("cityCode").is(queryDto.getCityCode());
        }

        if (!CollectionUtils.isEmpty(queryDto.getEstateUniqueUuids())) {
            criteria.and("estateUniqueUuid").in(queryDto.getEstateUniqueUuids());
        }

        if (StringUtils.isNotBlank(queryDto.getAreaUuid())) {
            criteria.and("districtUuid").is(queryDto.getAreaUuid());
        }
        if (StringUtils.isNotBlank(queryDto.getBusinessCircleUuid())) {
            criteria.and("areaUuid").is(queryDto.getBusinessCircleUuid());
        }
        if (StringUtils.isNotBlank(queryDto.getEstateName())) {
            criteria.and("estateName").regex(".*?" + queryDto.getEstateName() + ".*");
        }
        //均价
        if (queryDto.getMinSellPrice() != null && queryDto.getMaxSellPrice() != null) {
            criteria.and("sellPrice").gte(queryDto.getMinSellPrice()).lte(queryDto.getMaxSellPrice());
        } else if (queryDto.getMinSellPrice() != null) {
            criteria.and("sellPrice").gte(queryDto.getMinSellPrice());
        } else if (queryDto.getMaxSellPrice() != null) {
            criteria.and("sellPrice").lte(queryDto.getMaxSellPrice());
        }
        //楼龄
        if (queryDto.getBuildingYear() != 0) {
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR) - queryDto.getBuildingYear();
            Calendar calendar = Calendar.getInstance();
            calendar.clear();
            calendar.set(Calendar.YEAR, year);
            Date currYearFirst = calendar.getTime();
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String yearOfFirstDay = format.format(currYearFirst);
            criteria.and("completeYear").gte(yearOfFirstDay);
        }
        //类型
        if (StringUtils.isNotBlank(queryDto.getEstatetype())) {
            criteria.and("propertyUsage").is(queryDto.getEstatetype());
        }
        if (queryDto.getExistProperty() != null) {
            //有房源
            if (queryDto.getExistProperty()) {
                criteria.orOperator(Criteria.where("saleNum").gt(0), Criteria.where("rentNum").gt(0));
            } else {
                criteria.andOperator(Criteria.where("saleNum").is(0), Criteria.where("rentNum").is(0));
            }
        }
        query.addCriteria(criteria);
        return query;
    }

    private void createFindSort(Query queryCriteria, Integer sort) {
        queryCriteria.with(Sort.by(
                Sort.Order.desc("saleNum")
        ));
        queryCriteria.with(Sort.by(
                Sort.Order.desc("rentNum")
        ));
        EstateSortConstants enums = EstateSortConstants.getValueByCode(sort);
        if (null != enums) {
            if (enums.getValue().contains("_desc")) {
                String field = enums.getValue().replace("_desc", "");
                queryCriteria.with(Sort.by(
                        Sort.Order.desc(field)
                ));
            }

            if (enums.getValue().contains("_asc")) {
                String field = enums.getValue().replace("_asc", "");
                queryCriteria.with(Sort.by(
                        Sort.Order.asc(field)
                ));
            }
        }
    }

    @Override
    public List<EstateListDto> convertDomainToEstateListDto(List<Estate> propertyPage) {
        return propertyPage.stream().map(estateMapper::domainToListDto).collect(Collectors.toList());
    }

    @Override
    public Page<EstateListDto> convertDomainToEstateListDto(Page<Estate> propertyPage, String cityCode) {
        List<EstateListDto> content = new ArrayList<>();
        if (propertyPage.getTotalElements() > 0) {
            content = propertyPage.getContent().stream().map(estateMapper::domainToListDto).collect(Collectors.toList());
        }
        return PageableExecutionUtils.getPage(content, propertyPage.getPageable(), () -> propertyPage.getTotalElements());
    }

    @Override
    public List<Estate> findEstateDetailsByParams(EstateQueryDto queryDto) {
        // 1、拼查询公共条件
        Query query = new Query();
        QfContext qfContext = QfContextHolder.getContext();
        Criteria criteria = Criteria.where("corporationCode").is(qfContext.getCorporationCode());
        criteria.and("estateUniqueUuid").is(queryDto.getEstateUniqueUuid());
        query.addCriteria(criteria);
        return mongoTemplate.find(query, Estate.class);
    }

    private Query createAdminPageQuery(EstatePageQueryDto queryDto) {
        Query query = new Query();
        Criteria criteria = Criteria.where("corporationCode").is(queryDto.getCorporationCode());

        if (StringUtils.isNotBlank(queryDto.getCityCode())) {
            criteria.and("cityCode").is(queryDto.getCityCode());
        } else if (!CollectionUtils.isEmpty(queryDto.getCityCodes())){
            criteria.and("cityCode").in(queryDto.getCityCodes());
        }
        if (StringUtils.isNotBlank(queryDto.getDistrictUuid())) {
            criteria.and("districtUuid").is(queryDto.getDistrictUuid());
        }
        if (StringUtils.isNotBlank(queryDto.getAreaUuid())) {
            criteria.and("areaUuid").is(queryDto.getAreaUuid());
        }
        if (StringUtils.isNotBlank(queryDto.getPropertyUsage())) {
            criteria.and("propertyUsage").is(queryDto.getPropertyUsage());
        }
        if (StringUtils.isNotEmpty(queryDto.getFuzzyQueryStr())) {
            criteria.and("estateName").regex(".*?" + queryDto.getFuzzyQueryStr() + ".*");
        }
        if (StringUtils.isNotEmpty(queryDto.getSaleRentState())) {
            if ("1".equals(queryDto.getSaleRentState())) {
                criteria.and("saleNum").gt(0);
                criteria.and("rentNum").gt(0);
            } else if ("2".equals(queryDto.getSaleRentState())) {
                criteria.and("saleNum").gt(0);
                criteria.and("rentNum").is(0);
            } else if ("3".equals(queryDto.getSaleRentState())) {
                criteria.and("saleNum").is(0);
                criteria.and("rentNum").gt(0);
            } else if ("4".equals(queryDto.getSaleRentState())) {
                criteria.and("saleNum").is(0);
                criteria.and("rentNum").is(0);
            }
        }
        query.addCriteria(criteria);
        return query;
    }

    @Override
    public Page<EstatePageDto> getEstatePage(EstatePageQueryDto estatePageQueryDto, Pageable pageable) {
        // 1、拼查询公共条件
        Query query = createAdminPageQuery(estatePageQueryDto);
        // 2、拼分页参数
        query.with(pageable);
        // 4、查询记录条件
        long count = mongoTemplate.count(query, Estate.class);
        List<EstatePageDto> list = new ArrayList<>();
        if (count > 0) {
            Map<String, String> cityMap = cityCompanyService.getCityMap(estatePageQueryDto.getCorporationCode());
            // 6、分页查询数据
            List<Estate> content = mongoTemplate.find(query, Estate.class);
            for (Estate estate : content) {
                Query photoQuery = new Query();
                Criteria criteria = Criteria.where("corporationCode").is(estatePageQueryDto.getCorporationCode());
                criteria.and("estateUniqueUuid").is(estate.getEstateUniqueUuid());
                criteria.and("categoryName").ne("fangxing");
                photoQuery.addCriteria(criteria);
                Long photoNum = mongoTemplate.count(photoQuery, EstatePhoto.class);
                list.add(EstatePageDto.builder()
                        .estateUniqueUuid(estate.getEstateUniqueUuid())
                        .estateName(estate.getEstateName())
                        .rentNum(estate.getRentNum())
                        .saleNum(estate.getSaleNum())
                        .shortAddress(estate.getShortAddress())
                        .fullAddress(estate.getFullAddress())
                        .propertyUsage(estate.getPropertyUsage())
                        .city(cityMap.get(estate.getCityCode()))
                        .district(estate.getDistrictName())
                        .area(estate.getAreaName())
                        .photoNum(photoNum.intValue())
                        .build());
            }
        }
        return PageableExecutionUtils.getPage(list, pageable, () -> count);
    }

    /**
     * 获取公司水印设置
     * @return
     */
    private PropertyWaterMark getPropertyWaterMark() {
        QfContext context = QfContextHolder.getContext();
        List<CityCompany> cityCompanyList = cityCompanyRepository.findAllByCorporationCodeAndCityCodeAndMainCityFlag(context.getCorporationCode(), context.getCityCode(), 1);
        if (CollectionUtils.isEmpty(cityCompanyList)) {
            return null;
        }
        return cityCompanyList.get(0).getPropertyWaterMark();
    }

}
